"""
Main FastAPI application for CodeMCP Gateway.

Provides HTTP API interface for the CodeMCP framework, routing requests
to appropriate language-specific MCP servers.
"""

import asyncio
from typing import Dict, Any, Optional
from contextlib import asynccontextmanager

from fastapi import FastAPI, HTTPException, Depends, Request, BackgroundTasks
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
import uvicorn

from ..core.config import Config, load_config
from ..core.error_handler import handle_error, log_info, log_warning, CodeMCPError
from ..core.monitoring import HealthMonitor
from .routing import RequestRouter
from .session import SessionManager
from .middleware import setup_middleware
from .monitoring import TrafficMonitor
from .load_balancer import LoadBalancer


class GatewayApp:
    """Main Gateway application class."""
    
    def __init__(self, config: Config = None):
        self.config = config or load_config()
        self.router = RequestRouter(self.config)
        self.session_manager = SessionManager(self.config)
        self.load_balancer = LoadBalancer(self.config)
        self.traffic_monitor = TrafficMonitor(self.config)
        self.health_monitor = HealthMonitor("gateway")
        
        # FastAPI app instance will be created by create_app()
        self.app: Optional[FastAPI] = None
        self.is_initialized = False
        
    async def initialize(self):
        """Initialize all gateway components."""
        if self.is_initialized:
            return
            
        try:
            # Initialize components in order
            await self.load_balancer.initialize()
            await self.router.initialize(self.load_balancer)
            await self.session_manager.initialize()
            await self.traffic_monitor.initialize()
            await self.health_monitor.start()
            
            self.is_initialized = True
            log_info("Gateway application initialized successfully")
            
        except Exception as e:
            error_response = handle_error(e, {"component": "gateway_initialization"})
            raise CodeMCPError(f"Failed to initialize gateway: {error_response['message']}")
    
    async def shutdown(self):
        """Shutdown gateway components."""
        try:
            await self.health_monitor.stop()
            await self.traffic_monitor.shutdown()
            await self.session_manager.shutdown()
            await self.router.shutdown()
            await self.load_balancer.shutdown()
            
            log_info("Gateway application shutdown complete")
            
        except Exception as e:
            log_warning(f"Error during gateway shutdown: {e}")


# Global gateway instance
_gateway_instance: Optional[GatewayApp] = None


def get_gateway() -> GatewayApp:
    """Get the global gateway instance."""
    global _gateway_instance
    if _gateway_instance is None:
        _gateway_instance = GatewayApp()
    return _gateway_instance


@asynccontextmanager
async def lifespan(app: FastAPI):
    """FastAPI lifespan manager."""
    gateway = get_gateway()
    
    # Startup
    await gateway.initialize()
    
    yield
    
    # Shutdown
    await gateway.shutdown()


def create_app(config: Config = None) -> FastAPI:
    """
    Create and configure the FastAPI application.
    
    Args:
        config: Configuration object (optional)
        
    Returns:
        Configured FastAPI application
    """
    # Create gateway instance
    global _gateway_instance
    if config:
        _gateway_instance = GatewayApp(config)
    
    gateway = get_gateway()
    
    # Create FastAPI app
    app = FastAPI(
        title="CodeMCP Gateway",
        description="HTTP API Gateway for CodeMCP Framework",
        version="1.0.0",
        lifespan=lifespan,
        docs_url="/docs",
        redoc_url="/redoc",
        openapi_url="/openapi.json"
    )
    
    # Setup middleware
    setup_middleware(app, gateway.config)
    
    # Register routes
    register_routes(app, gateway)
    
    # Store reference to app in gateway
    gateway.app = app
    
    return app


def register_routes(app: FastAPI, gateway: GatewayApp):
    """Register all API routes."""
    # Import route modules
    from ..api.routes.analysis import router as analysis_router
    from ..api.routes.health import router as health_router  
    from ..api.routes.admin import router as admin_router
    
    # Include routers
    app.include_router(analysis_router, prefix="/api/v1", tags=["analysis"])
    app.include_router(health_router, prefix="/api/v1", tags=["health"])
    app.include_router(admin_router, prefix="/api/v1", tags=["admin"])
    
    # Root endpoint
    @app.get("/")
    async def root():
        """Root endpoint with basic information."""
        return {
            "service": "CodeMCP Gateway", 
            "version": "1.0.0",
            "status": "running",
            "docs": "/docs"
        }
    
    # Global exception handler
    @app.exception_handler(Exception)
    async def global_exception_handler(request: Request, exc: Exception):
        """Global exception handler."""
        error_response = handle_error(exc, {
            "path": str(request.url),
            "method": request.method,
            "client": getattr(request.client, "host", "unknown") if request.client else "unknown"
        })
        
        # Record the error in traffic monitor
        if gateway.is_initialized:
            await gateway.traffic_monitor.record_error(request, error_response)
        
        # Determine status code
        if isinstance(exc, HTTPException):
            status_code = exc.status_code
        elif isinstance(exc, CodeMCPError):
            status_code = 400
        else:
            status_code = 500
            
        return JSONResponse(
            status_code=status_code,
            content=error_response
        )
    
    # Request/response middleware for traffic monitoring
    @app.middleware("http")
    async def traffic_monitoring_middleware(request: Request, call_next):
        """Middleware to monitor traffic."""
        if not gateway.is_initialized:
            response = await call_next(request)
            return response
            
        # Record request
        start_time = await gateway.traffic_monitor.record_request(request)
        
        try:
            # Process request
            response = await call_next(request)
            
            # Record response
            await gateway.traffic_monitor.record_response(
                request, response, start_time
            )
            
            return response
            
        except Exception as e:
            # Record error
            await gateway.traffic_monitor.record_error(request, {"error": str(e)})
            raise


# Create default app instance
app = create_app()


async def run_server(
    host: str = "localhost",
    port: int = 8889,
    workers: int = 1,
    reload: bool = False,
    log_level: str = "info"
):
    """
    Run the gateway server.
    
    Args:
        host: Host to bind to
        port: Port to bind to  
        workers: Number of worker processes
        reload: Enable auto-reload for development
        log_level: Logging level
    """
    config = uvicorn.Config(
        app="codemcp.gateway.app:app",
        host=host,
        port=port,
        workers=workers if not reload else 1,  # reload doesn't work with multiple workers
        reload=reload,
        log_level=log_level,
        access_log=True
    )
    
    server = uvicorn.Server(config)
    
    log_info(f"Starting CodeMCP Gateway on {host}:{port}")
    log_info(f"API Documentation available at http://{host}:{port}/docs")
    
    await server.serve()


if __name__ == "__main__":
    # Development server
    asyncio.run(run_server(
        host="0.0.0.0",
        port=8889,
        reload=True,
        log_level="debug"
    ))